#include "barcode_printer.h"
#include <algorithm>
#include <iostream>

// 静态成员初始化
const std::map<PaperType, PaperInfo> BarcodePrinter::paperTypes_ = {
    {PAPER_70591, {38.0f, 25.0f, "38*25mm"}},
    {PAPER_70277, {50.0f, 30.0f, "50*30mm"}},
    {PAPER_240058, {30.0f, 15.0f, "30*15mm"}},
    {PAPER_70296, {40.0f, 20.0f, "40*20mm"}},
    {PAPER_70279, {30.0f, 20.0f, "30*20mm"}},
    {PAPER_70355, {24.0f, 12.0f, "24*12mm"}}
};

// 构造函数
BarcodePrinter::BarcodePrinter() : isInitialized_(false) {
}

// 析构函数
BarcodePrinter::~BarcodePrinter() {
    cleanup();
}

// 初始化SDK
bool BarcodePrinter::initialize() {
    if (isInitialized_) {
        return true;
    }
    
    if (!Printer::loadPrinterApiDll()) {
        std::cerr << "Error: Failed to load printer API DLL" << std::endl;
        return false;
    }
    
    if (!Printer::initSdk(RESOURCE_PATH)) {
        std::cerr << "Error: Failed to initialize SDK" << std::endl;
        Printer::freePrinterApiDll();
        return false;
    }
    
    isInitialized_ = true;
    return true;
}

// 清理资源
void BarcodePrinter::cleanup() {
    if (isInitialized_) {
        Printer::disconnectPrinter();
        Printer::unInitSdk();
        Printer::freePrinterApiDll();
        isInitialized_ = false;
    }
}

// 计算不同纸张类型的坐标
PositionInfo BarcodePrinter::calculatePosition(PaperType paperType, PrintMode mode) {
    PositionInfo pos;
    PaperInfo paper = paperTypes_.at(paperType);
    
    if (mode == SINGLE_BARCODE) {
        // 单条码模式：二维码居中
        float qrSize = std::min(paper.width * 0.6f, paper.height * 0.6f); // 二维码占纸张60%空间
        pos.qr_width = qrSize;
        pos.qr_height = qrSize;
        pos.qr_x = (paper.width - qrSize) / 2.0f;  // 水平居中
        pos.qr_y = (paper.height - qrSize) / 2.0f; // 垂直居中
        
        // 单条码模式不需要文本位置
        pos.text_x = pos.text_y = pos.text_width = pos.text_height = 0;
        pos.text_line_height = 0;
    } else {
        // 带文本信息模式：条码居左，文本居右中
        float qrSize = std::min(paper.width * 0.4f, paper.height * 0.8f); // 二维码占40%宽度，80%高度
        pos.qr_width = qrSize;
        pos.qr_height = qrSize;
        pos.qr_x = 2.0f;  // 左边距2mm
        pos.qr_y = (paper.height - qrSize) / 2.0f; // 垂直居中
        
        // 文本区域：右侧剩余空间
        pos.text_x = qrSize + 4.0f;  // 二维码右边距4mm
        pos.text_y = 2.0f;  // 上边距2mm
        pos.text_width = paper.width - pos.text_x - 2.0f;  // 右边距2mm
        pos.text_height = paper.height - 4.0f;  // 上下边距各2mm
        pos.text_line_height = 3.0f;  // 每行文本高度3mm
    }
    
    return pos;
}

// 统一打印函数
bool BarcodePrinter::printBarcode(const PrintInfo& printInfo) {
    if (!isInitialized_) {
        std::cerr << "Error: SDK not initialized" << std::endl;
        return false;
    }
    
    // 验证参数
    if (printInfo.printType != 1 && printInfo.printType != 2) {
        std::cerr << "Error: Invalid print type " << printInfo.printType << std::endl;
        return false;
    }
    
    PaperType paperType = static_cast<PaperType>(printInfo.paperType);
    if (paperTypes_.find(paperType) == paperTypes_.end()) {
        std::cerr << "Error: Unsupported paper type " << printInfo.paperType << std::endl;
        return false;
    }
    
    // 验证条码信息长度
    if (strlen(printInfo.code) != 40) {
        std::cerr << "Error: Barcode code must be 40 characters, current length: " << strlen(printInfo.code) << std::endl;
        return false;
    }
    
    // 检查打印机连接状态
    if (!Printer::isConnected()) {
        std::cerr << "Error: Printer is not connected" << std::endl;
        return false;
    }
    std::cout << "Printer connection status: Connected" << std::endl;
    
    PrintMode mode = (printInfo.printType == 1) ? SINGLE_BARCODE : BARCODE_WITH_TEXT;
    
    std::cout << "Starting " << (mode == SINGLE_BARCODE ? "single barcode" : "barcode with text") << " print mode..." << std::endl;
    
    // 获取纸张信息
    PaperInfo paper = paperTypes_.at(paperType);
    std::cout << "Paper type: " << paper.name << std::endl;
    
    // 计算坐标
    PositionInfo pos = calculatePosition(paperType, mode);
    std::cout << "QR code position: (" << pos.qr_x << ", " << pos.qr_y << ") size: " << pos.qr_width << "x" << pos.qr_height << std::endl;
    if (mode == BARCODE_WITH_TEXT) {
        std::cout << "Text area: (" << pos.text_x << ", " << pos.text_y << ") size: " << pos.text_width << "x" << pos.text_height << std::endl;
    }
    
    // 设置打印参数
    StartJobParameter param{};
    param.printLabelType = 1;  // 间隙纸
    param.printDensity = 5;    // 浓度
    param.printMode = 1;       // 热敏
    param.colorType = 0;
    param.qualityType = 1;
    param.printCount = 1;
    
    // 开始打印作业
    std::cout << "Starting print job with parameters:" << std::endl;
    std::cout << "  printLabelType: " << param.printLabelType << std::endl;
    std::cout << "  printDensity: " << param.printDensity << std::endl;
    std::cout << "  printMode: " << param.printMode << std::endl;
    std::cout << "  colorType: " << param.colorType << std::endl;
    std::cout << "  qualityType: " << param.qualityType << std::endl;
    std::cout << "  printCount: " << param.printCount << std::endl;
    
    if (!Printer::startJob_New(param)) {
        int errorCode = Printer::getLastPrinterError();
        std::cerr << "Failed to start print job, error code: " << errorCode << std::endl;
        std::cerr << "Error description: ";
        switch(errorCode) {
            case 0: std::cerr << "No error (E_NO_ERROR)"; break;
            case 1: std::cerr << "Box opened (E_BOX_OPENED)"; break;
            case 2: std::cerr << "No paper (E_NO_PAPER)"; break;
            case 3: std::cerr << "Low voltage (E_LOW_VOLTAGE)"; break;
            case 4: std::cerr << "Battery abnormal (E_BATTERY_UNNORMAL)"; break;
            case 5: std::cerr << "Manual stop (E_HANDLE_STOP)"; break;
            case 6: std::cerr << "Data error (E_DATA_ERROR)"; break;
            case 7: std::cerr << "High temperature (E_HIGH_TEMPRATURE)"; break;
            case 8: std::cerr << "Paper out (E_PAPER_OUT)"; break;
            case 9: std::cerr << "Is printing (E_IS_PRINTING)"; break;
            case 10: std::cerr << "No printhead detected (E_NO_PRINTHEAD_DETECT)"; break;
            case 11: std::cerr << "Temperature low (E_TEMPRATURE_LOW)"; break;
            case 12: std::cerr << "Printhead flexible (E_PRINTHEAD_FLEXIBLE)"; break;
            case 13: std::cerr << "No carbon bands (E_NO_CARBON_BANDS)"; break;
            case 14: std::cerr << "No match carbon bands (E_NO_MATCH_CARBON_BANDS)"; break;
            case 15: std::cerr << "Used carbon bands (E_USED_CARBON_BANDS)"; break;
            case 16: std::cerr << "Paper type not supported (E_PARPER_UNNORMAL)"; break;
            case 17: std::cerr << "Set paper type failed (E_SET_PARPER_FAIL)"; break;
            case 18: std::cerr << "Set print mode failed (E_SET_PRINT_MODE_FAIL)"; break;
            case 19: std::cerr << "Set density failed (E_SET_DENSITY_FAIL)"; break;
            case 20: std::cerr << "Write RFID failed (E_WRITE_RFID_FAIL)"; break;
            case 21: std::cerr << "Margin error (E_MARGIN_ERROR)"; break;
            case 22: std::cerr << "Timeout (E_TIMEOUT)"; break;
            case 23: std::cerr << "Disconnect (E_DISCONNECT)"; break;
            case 24: std::cerr << "Drawing board error (E_DRAWBOARD_ERROR)"; break;
            case 25: std::cerr << "Orientation error (E_ORIENTATION_ERROR)"; break;
            case 26: std::cerr << "JSON error (E_JSON_ERROR)"; break;
            case 27: std::cerr << "Paper out S (E_PAPER_OUT_S)"; break;
            case 28: std::cerr << "Check paper (E_CHECK_PAPER)"; break;
            case 29: std::cerr << "Print mode (E_PRINT_MODE)"; break;
            case 30: std::cerr << "Set density no support (E_SET_DENSITY_NO_SUPPORT)"; break;
            case 31: std::cerr << "Print mode no support (E_PRINT_MODE_NO_SUPPORT)"; break;
            case 255: std::cerr << "Unknown error (E_UNKNOW_ERROR)"; break;
            default: std::cerr << "Unknown error code"; break;
        }
        std::cerr << std::endl;
        return false;
    }
    
    std::cout << "Print job started successfully!" << std::endl;
    
    // 初始化画板
    if (!Printer::InitDrawingBoard(paper.width, paper.height, 0, "ZT001.ttf", 0, 0)) {
        std::cerr << "Failed to initialize drawing board, error code: " << Printer::getLastPrinterError() << std::endl;
        Printer::endJob();
        return false;
    }
    
    // 绘制二维码
    std::string qrContent = u8"" + std::string(printInfo.code);
    if (!Printer::DrawLableQrCode(pos.qr_x, pos.qr_y, pos.qr_width, pos.qr_height, 
                                  qrContent.c_str(), 31, 0)) { // 31=QR_CODE
        std::cerr << "Failed to draw QR code, error code: " << Printer::getLastPrinterError() << std::endl;
        Printer::endJob();
        return false;
    }
    
    // 如果是带文本信息模式，绘制商品信息文本
    if (mode == BARCODE_WITH_TEXT) {
        float currentY = pos.text_y;
        for (int i = 0; i < 3; i++) {
            if (strlen(printInfo.info[i]) > 0) {  // 只绘制非空信息
                std::string text = u8"" + std::string(printInfo.info[i]);
                bool fontStyle[4] = {false, false, false, false}; // 无特殊样式
                
                if (!Printer::DrawLableText(pos.text_x, currentY, pos.text_width, pos.text_line_height,
                                            text.c_str(), "ZT001.ttf", 3.0f, 0, // 字体大小3mm
                                            0, 0, // 左对齐，顶对齐
                                            2, // 宽度固定，高度自适应
                                            0, 0, fontStyle)) {
                    std::cerr << "Failed to draw text, error code: " << Printer::getLastPrinterError() << std::endl;
                    Printer::endJob();
                    return false;
                }
                currentY += pos.text_line_height + 1.0f; // 行间距1mm
            }
        }
    }
    
    // 提交打印
    if (!Printer::commitJob()) {
        std::cerr << "Failed to commit print, error code: " << Printer::getLastPrinterError() << std::endl;
        Printer::endJob();
        return false;
    }
    
    // 结束作业
    Printer::endJob();
    std::cout << (mode == SINGLE_BARCODE ? "Single barcode" : "Barcode with text") << " print completed" << std::endl;
    return true;
}